#!/usr/bin/env python
# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
from pylab import mpl
from datetime import datetime, timedelta
from django.core.exceptions import ValidationError
from django.db.utils import DataError
from django.db.models import Q
from web.util.dto_util import DtoUtil
from web.util.datetime_util import DatetimeUtil
from web.util.math_util import MathUtil
from web.constants.k_line_period_type import KLinePeriodType
from web.constants.datetime_format import DatetimeFormat
from web.manager.log_manager import LogManager
from web.models.commodity_future_week_data import CommodityFutureWeekData
from web.service.base_service import BaseService
from web.config.create_week_picture_config import CreateWeekPictureConfig
from web.config.commodity_future_week_data_config import CommodityFutureWeekDataConfig

Logger = LogManager.get_logger(__name__)

"""
CommodityFutureWeekData的service类
"""


class CommodityFutureWeekDataService(BaseService):

    ########################################### 全量计算数据 ########################################

    def write_week_basic_data(self):
        """
        计算周线级别基础数据
        """

        Logger.info("计算周线级别基础数据")

        self.commodity_future_week_data_dao.write_week_basic_data()

    def write_week_all_ma(self):
        """
        计算周线级别全部MA数据
        """

        Logger.info("计算周线级别全部MA数据")

        self.commodity_future_week_data_dao.write_week_all_ma()

    def write_week_all_kd(self):
        """
        计算周线级别全部KD数据
        """

        Logger.info("计算周线级别全部KD数据")

        self.commodity_future_week_data_dao.write_week_all_kd()

    def write_week_all_macd(self):
        """
        计算周线级别全部MACD数据
        """

        Logger.info("计算周线级别全部MACD数据")

        self.commodity_future_week_data_dao.write_week_all_macd()

    def write_week_all_boll(self):
        """
        计算周线级别全部BOLL数据
        """

        Logger.info("计算周线级别全部BOLL数据")

        self.commodity_future_week_data_dao.write_week_all_boll()

    def write_week_all_ha(self):
        """
        计算周线级别全部HA数据
        """

        Logger.info("计算周线级别全部HA数据")

        self.commodity_future_week_data_dao.write_week_all_ha()

    ########################################### 增量计算数据 ########################################

    def write_week_by_date(self):
        """
        根据日期，计算周线级别某一个交易周的基础数据
        """

        Logger.info("根据日期，计算周线级别交易周[%s]和[%s]的基础数据",
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_By_Begin_Date,
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_By_End_Date)

        self.commodity_future_week_data_dao.write_week_by_date(
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_By_Begin_Date,
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_By_End_Date)

    def write_week_ma_by_date(self):
        """
        根据日期，计算周线级别某一个交易周的MA数据
        """

        Logger.info("根据日期，计算周线级别交易周[%s]和[%s]的MA数据",
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Ma_By_Begin_Date,
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Ma_By_End_Date)

        self.commodity_future_week_data_dao.write_week_ma_by_date(
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Ma_By_Begin_Date,
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Ma_By_End_Date)

    def write_week_kd_by_date(self):
        """
        根据日期，计算周线级别某一个交易周的KD数据
        """

        Logger.info("根据日期，计算周线级别交易周[%s]和[%s]的KD数据",
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Kd_By_Begin_Date,
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Kd_By_End_Date)

        self.commodity_future_week_data_dao.write_week_kd_by_date(
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Kd_By_Begin_Date,
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Kd_By_End_Date)

    def write_week_macd_by_date(self):
        """
        根据日期，计算周线级别某一个交易周的MACD数据
        """

        Logger.info("根据日期，计算周线级别交易周[%s]和[%s]的MACD数据",
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Macd_By_Begin_Date,
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Macd_By_End_Date)

        self.commodity_future_week_data_dao.write_week_macd_by_date(
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Macd_By_Begin_Date,
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Macd_By_End_Date)

    def write_week_boll_by_date(self):
        """
        根据日期，计算周线级别某一个交易周的BOLL数据
        """

        Logger.info("根据日期，计算周线级别交易周[%s]和[%s]的BOLL数据",
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Boll_By_Begin_Date,
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Boll_By_End_Date)

        self.commodity_future_week_data_dao.write_week_boll_by_date(
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Boll_By_Begin_Date,
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Boll_By_End_Date)

    def write_week_ha_by_date(self):
        """
        根据日期，计算周线级别某一个交易周的HA数据
        """

        Logger.info("根据日期，计算周线级别交易周[%s]和[%s]的HA数据",
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Ha_By_Begin_Date,
                    CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Ha_By_End_Date)

        self.commodity_future_week_data_dao.write_week_ha_by_date(
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Ha_By_Begin_Date,
            CommodityFutureWeekDataConfig.Commodity_Future_Week_Data_Ha_By_End_Date)

    #################################################### 创建图片 ################################################
    def create_price_change_up_percentage_picture(self):
        """
        创建图片：周线级别上涨的期货的百分比
        """

        Logger.info("周线级别上涨的期货的百分比，时间从[%s]至[%s]", CreateWeekPictureConfig.Price_Change_Up_Percentage_Begin_Date,
                    CreateWeekPictureConfig.Price_Change_Up_Percentage_End_Date)

        begin_date_and_end_date_tuple = self.stock_index_week_dao.find_begin_data_and_end_date_between_and_order_by(
            CreateWeekPictureConfig.Price_Change_Up_Percentage_Begin_Date,
            CreateWeekPictureConfig.Price_Change_Up_Percentage_End_Date)

        transaction_date_array = list()
        price_change_up_percentage_array = list()
        middle_line_array = list()
        min_begin_date_and_max_end_date_5_date_array = list()
        for begin_date_and_end_date in begin_date_and_end_date_tuple:
            percentage_tuple = self.commodity_future_date_data_dao.find_date_price_change_up_percentage_between_transaction_date(
                DatetimeUtil.datetime_to_str(begin_date_and_end_date[0], DatetimeFormat.Date_Format_With_Line),
                DatetimeUtil.datetime_to_str(begin_date_and_end_date[1], DatetimeFormat.Date_Format_With_Line))

            # 5日均线
            min_begin_date_and_max_end_date_5_date_tuple = self.stock_index_week_dao.find_max_end_date_and_min_begin_date_between(
                DatetimeUtil.datetime_to_str(begin_date_and_end_date[0], DatetimeFormat.Date_Format_With_Line),
                DatetimeUtil.datetime_to_str(begin_date_and_end_date[1], DatetimeFormat.Date_Format_With_Line), 5)
            average_price_change_5_date_tuple = self.commodity_future_date_data_dao.average_price_change_up_percentage_between_transaction_date(
                DatetimeUtil.datetime_to_str(min_begin_date_and_max_end_date_5_date_tuple[0][0],
                                             DatetimeFormat.Date_Format_With_Line),
                DatetimeUtil.datetime_to_str(min_begin_date_and_max_end_date_5_date_tuple[0][1],
                                             DatetimeFormat.Date_Format_With_Line), 5)

            for percentage in percentage_tuple:
                transaction_date_array.append(
                    DatetimeUtil.datetime_to_str(begin_date_and_end_date[1], DatetimeFormat.Date_Format_With_Line))
                price_change_up_percentage_array.append(percentage[0])
                middle_line_array.append(50)
                min_begin_date_and_max_end_date_5_date_array.append(average_price_change_5_date_tuple[0][0])

        # 创建一个新的图表
        fig, ax = plt.subplots(figsize=(18, 8))

        # 关闭交互模式
        plt.ioff()

        mpl.rcParams["font.sans-serif"] = ["SimHei"]

        # 创建折线图
        ax.plot(transaction_date_array, middle_line_array, label='中轴线', linewidth=0.5,
                marker='o',
                color='red')
        ax.plot(transaction_date_array, price_change_up_percentage_array, label='上涨的期货的百分比',
                linewidth=0.5,
                marker='o', color='black')
        ax.plot(transaction_date_array, min_begin_date_and_max_end_date_5_date_array, label='上涨的期货的百分比（5日均线）',
                linewidth=0.5,
                marker='o', color='blue')
        plt.legend()
        plt.title('周线级别上涨的期货的百分比')
        plt.xlabel('时间')
        plt.ylabel('百分比')

        # 分辨率
        plt.rcParams['savefig.dpi'] = 300

        # 显示图例
        # plt.legend()

        # 保存图表
        plt.savefig(CreateWeekPictureConfig.Price_Change_Up_Percentage_Save_Path)

        # 显示图表
        # plt.show()

        # 关闭图表
        plt.close()

    def create_week_average_kd_picture(self):
        """
        创建图片：根据开始时间和结束时间，周线级别平均KD
        """
        Logger.info("创建图片：根据开始时间和结束时间，周线级别平均KD，时间从[%s]至[%s]", CreateWeekPictureConfig.Average_KD_Begin_Date,
                    CreateWeekPictureConfig.Average_KD_End_Date)

        begin_date_and_end_date_tuple = self.stock_index_week_dao.find_begin_data_and_end_date_between_and_order_by(
            CreateWeekPictureConfig.Average_KD_Begin_Date,
            CreateWeekPictureConfig.Average_KD_End_Date)

        transaction_date_array = list()
        average_k_array = list()
        average_d_array = list()
        unite_relative_price_index_date_close_price_array = list()
        for begin_date_and_end_date in begin_date_and_end_date_tuple:
            average_kd_tuple = self.commodity_future_week_data_dao.find_average_kd_by_begin_date_and_end_date(
                DatetimeUtil.datetime_to_str(begin_date_and_end_date[0], DatetimeFormat.Date_Format_With_Line),
                DatetimeUtil.datetime_to_str(begin_date_and_end_date[1], DatetimeFormat.Date_Format_With_Line))
            average_k_array.append(average_kd_tuple[0][0])
            average_d_array.append(average_kd_tuple[0][1])
            transaction_date_array.append(begin_date_and_end_date[0])
            unite_relative_price_index_date = self.unite_relative_price_index_date_dao.find_by_transaction_date(
                DatetimeUtil.datetime_to_str(begin_date_and_end_date[1], DatetimeFormat.Date_Format_With_Line))
            unite_relative_price_index_date_close_price_array.append(unite_relative_price_index_date.close_price)

        # 创建一个新的图表
        fig, ax = plt.subplots(figsize=(18, 8))

        # 关闭交互模式
        plt.ioff()

        mpl.rcParams["font.sans-serif"] = ["SimHei"]

        # 创建折线图
        ax.plot(transaction_date_array, MathUtil.normalize(average_k_array)[0], label='平均K值', linewidth=0.5,
                marker='o',
                color='blue')
        ax.plot(transaction_date_array, MathUtil.normalize(average_d_array)[0], label='平均D值',
                linewidth=0.5,
                marker='o', color='green')
        ax.plot(transaction_date_array, MathUtil.normalize(unite_relative_price_index_date_close_price_array)[0],
                label='统一相对价格指数周线级别收盘价',
                linewidth=0.5,
                marker='o', color='red')
        plt.legend()
        plt.title('周线级别平均KD')
        plt.xlabel('时间')
        plt.ylabel('百分比')

        # 分辨率
        plt.rcParams['savefig.dpi'] = 300

        # 显示图例
        # plt.legend()

        # 保存图表
        plt.savefig(CreateWeekPictureConfig.Average_KD_Save_Path)

        # 显示图表
        # plt.show()

        # 关闭图表
        plt.close()
